#include "IAP.h"

uint32_t GetSector(uint32_t Address);
void FLASH_WRITE_SUCCESS(uint8_t KEY)
{
    switch (KEY)
    {
    case 1:
        write_flash_key(FLASH_OPERATION_KEY_CODE_0);
        break;
    case 2:
        write_flash_key(FLASH_OPERATION_KEY_CODE_1);
        break;
    default:
        write_flash_key(FLASH_OPERATION_KEY_CODE_0);
        break;
    }
    NVIC_SystemReset();
}

void write_flash_key(uint32_t FLASH_OPERATION_KEY)
{
    HAL_FLASH_Unlock();
    FLASH_EraseInitTypeDef erase;
    uint32_t SectorError = 0;
    erase.Banks = FLASH_BANK_1;
    erase.NbSectors = 1;
    erase.Sector = FLASH_SECTOR_3;
    erase.TypeErase = FLASH_TYPEERASE_SECTORS;
    erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
    HAL_FLASHEx_Erase(&erase, &SectorError);
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_KEY_ADDR, FLASH_OPERATION_KEY);
    HAL_FLASH_Lock();
}
volatile uint8_t down_flag = 0;
void SystemUpdate(UPDATA *updata)
{
    HAL_FLASH_Unlock();
    down_flag = 0;
    if (updata->start_addr == FLASH_START_ADDR)
    {
        FLASH_EraseInitTypeDef erase;
        uint32_t SectorError = 0;
        erase.Banks = FLASH_BANK_1;
        erase.NbSectors = 2;
        erase.Sector = GetSector(updata->start_addr);
        erase.TypeErase = FLASH_TYPEERASE_SECTORS;
        erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
        HAL_FLASHEx_Erase(&erase, &SectorError);
    }
    // printf("addr: %d , len : %d , data1 : %08x\n", updata->start_addr, updata->data_size, ((uint32_t *)updata->data)[0]);
    Flash_Write_Word(updata->data, updata->start_addr, updata->data_size);
    // printf("%08x %08x\n", *((uint32_t *)updata->start_addr), updata->start_addr);
    down_flag = 1;
    HAL_FLASH_Lock();
}

void Flash_Write_Word(uint8_t *buffer, uint32_t addr, uint16_t Len)
{
    for (size_t i = 0; i < Len; i++)
    {
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addr, *buffer);
        addr++;
        buffer++;
    }
}

uint32_t read_flash_key(void)
{
    return *((uint32_t *)FLASH_KEY_ADDR);
}

void (*systemBootJump)(void);
// __IO uint32_t BootAddr = 0x1FFF0000;
__IO uint32_t BootAddr = FLASH_START_ADDR;
void JumpToFunction(void)
{
    uint32_t i = 0;
    // __set_PRIMASK(1);//禁止全局中断
    __disable_irq();
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
    HAL_RCC_DeInit();
    HAL_DeInit();
    for (i = 0; i < 8; i++)
    {
        NVIC->ICER[i] = 0xFFFFFFFF;
        NVIC->ICPR[i] = 0xFFFFFFFF;
    }
    // __set_PRIMASK(0);
    __enable_irq();
    systemBootJump = (void (*)(void))(*((uint32_t *)(BootAddr + 4)));
    __set_MSP(*(uint32_t *)BootAddr);
    __set_CONTROL(0); //在RTOS工程很重要，设置为特权模式，使用MSP指针
    systemBootJump();
}

uint32_t GetSector(uint32_t Address)
{
    uint32_t sector = 0;

    if ((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
    {
        sector = FLASH_SECTOR_0;
    }
    else if ((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
    {
        sector = FLASH_SECTOR_1;
    }
    else if ((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
    {
        sector = FLASH_SECTOR_2;
    }
    else if ((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
    {
        sector = FLASH_SECTOR_3;
    }
    else if ((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
    {
        sector = FLASH_SECTOR_4;
    }
    else if ((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
    {
        sector = FLASH_SECTOR_5;
    }
    else if ((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
    {
        sector = FLASH_SECTOR_6;
    }
    else if ((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
    {
        sector = FLASH_SECTOR_7;
    }
    else if ((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
    {
        sector = FLASH_SECTOR_8;
    }
    else if ((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
    {
        sector = FLASH_SECTOR_9;
    }
    else if ((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
    {
        sector = FLASH_SECTOR_10;
    }
    else /* (Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11) */
    {
        sector = FLASH_SECTOR_11;
    }

    return sector;
}